package common

import (
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

var (
	jwtSecret = []byte("v3.2.0+incompatible")
)

// 定义jwt的claims
type JwtClaims struct {
	Username string
	jwt.StandardClaims
}

// 生成jwt
func GenerateToken(username string) (string, error) {
	claims := &JwtClaims{
		Username: username,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: time.Now().Add(2160 * time.Hour).Unix(),
			Issuer:    "Charles",
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(jwtSecret)
}

// 解析jwt
func ParseToken(tokenString string) (*JwtClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &JwtClaims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte(jwtSecret), nil
	})
	if err != nil {
		return nil, err
	}
	claims, ok := token.Claims.(*JwtClaims)
	if !ok {
		return nil, jwt.ErrSignatureInvalid
	}
	return claims, nil
}

// 中间件
func JwtMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		tokenString := c.Request.Header.Get("Authorization")

		// 检查是否包含 Bearer 前缀
		//if strings.HasPrefix(tokenString, "Bearer ") {
		//	tokenString = tokenString[len("Bearer "):]
		//}

		if tokenString == "" {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"error": "Token is missing"})
			return
		}
		claims, err := ParseToken(tokenString)
		if err != nil {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"error": "Invalid token"})
			return
		}
		c.Set("claims", claims)
		c.Next()
	}
}

func RefreshToken(c *gin.Context) {
	tokenString := c.Request.Header.Get("Authorization")
	if tokenString == "" {
		c.JSON(http.StatusUnauthorized, gin.H{
			"error": "Token is missing"})
		return
	}
	claims, err := ParseToken(tokenString)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
		return
	}
	if time.Now().Unix() > claims.ExpiresAt-(5*60) {
		newToken, err := GenerateToken(claims.Username)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"error": "Failed to generate new token"})
			return
		}
		c.JSON(http.StatusOK, gin.H{"new_token": newToken})
	} else {
		c.JSON(http.StatusOK, gin.H{"message": "Token is still valid"})
	}
}
